home *** CD-ROM | disk | FTP | other *** search
/ Aminet 15 / Aminet 15 - Nov 1996.iso / Aminet / dev / misc / libx11.lha / libX11 / drawing.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-22  |  31.1 KB  |  1,256 lines

  1. /* Copyright (c) 1996 by Terje Pedersen.  All Rights Reserved   */
  2. /*                                                              */
  3. /* By using this code you will agree to these terms:            */
  4. /*                                                              */
  5. /* 1. You may not use this code for profit in any way or form   */
  6. /*    unless an agreement with the author has been reached.     */
  7. /*                                                              */
  8. /* 2. The author is not responsible for any damages caused by   */
  9. /*    the use of this code.                                     */
  10. /*                                                              */
  11. /* 3. All modifications are to be released to the public.       */
  12. /*                                                              */
  13. /* Thats it! Have fun!                                          */
  14. /* TP                                                           */
  15. /*                                                              */
  16.  
  17. /***
  18.    NAME
  19.      drawing
  20.    PURPOSE
  21.      add some drawing funcs to libX11
  22.    NOTES
  23.      
  24.    HISTORY
  25.      Terje Pedersen - Oct 22, 1994: Created.
  26. ***/
  27.  
  28. /*#define DOCLIPPING*/
  29. /*#define TEST*/
  30.  
  31. #include <intuition/intuition.h>
  32. #include <intuition/intuitionbase.h>
  33.  
  34. #include <graphics/gfx.h>
  35. #include <graphics/gfxbase.h>
  36. #include <graphics/gfxmacros.h>
  37. #include <graphics/displayinfo.h>
  38. #include <devices/timer.h>
  39.  
  40. #include <proto/intuition.h>
  41. #include <proto/graphics.h>
  42. #include <proto/gadtools.h>
  43. #include <proto/layers.h>
  44.  
  45. #include <dos.h>
  46. #include <signal.h>
  47. #include <stdlib.h>
  48. #include <time.h>
  49. #include <stdio.h>
  50. #include <math.h>
  51.  
  52. #include "libX11.h"
  53.  
  54. /*#define XLIB_ILLEGAL_ACCESS 1*/
  55.  
  56. #include <X11/X.h>
  57. #include <X11/Xlib.h>
  58. /*
  59. #include <X11/Xutil.h>
  60. #include <X11/Intrinsic.h>
  61. #include <X11/IntrinsicP.h>
  62. #include <X11/CoreP.h>
  63. */
  64. /*
  65. #include <libraries/mui.h>
  66. #include <proto/muimaster.h>
  67. */
  68. #include <X11/Xlibint.h>
  69.  
  70. #include "amigax_proto.h"
  71. #include "amiga_x.h"
  72.  
  73. /*
  74. #define DEBUGXEMUL_ENTRY 1
  75. */
  76. /*******************************************************************************************/
  77. /* externals */
  78. extern GC      amiga_gc;
  79.  
  80. extern struct Screen *Scr,*wb;
  81.  
  82. extern int X_relx,X_rely,X_right,X_bottom,X_width,X_height;
  83. extern int Xdash;
  84. extern Window prevwin;
  85. extern GC prevgc;
  86.  
  87. #define M_PI      3.14159265358979323846
  88. #define rad(x) ((double)(x)*M_PI/180)
  89. /*******************************************************************************************/
  90. /* prototypes */
  91.  
  92. polygon_draw(struct RastPort *drp,XPoint *aPoints,int nPoints,int xmin,int ymin);
  93. X11FillPolygon(struct RastPort *drp,XPoint *points,int nPoints,int xmin,int ymin, char black);
  94.  
  95. XPoint *polygon_clip( int nPoints,
  96.               XPoint *points,
  97.               boolean bFill,
  98.               int PolygonType,
  99.               int *nPointsReturn,
  100.               int move,
  101.               int end );
  102.  
  103. enum {
  104.   Polygon_Open=1,
  105.   Polygon_Closed
  106. };
  107.  
  108. /*******************************************************************************************/
  109. extern struct RastPort drawrp,backrp;
  110. extern struct RastPort *drp;
  111.  
  112. extern void _Xfillfit(Window,int);
  113. extern int X11check_size(Window,int,int);
  114.  
  115. /*******************************************************************************************/
  116. /* globals */
  117.  
  118. XPoint xp[4];
  119. XPoint *aPoints;
  120. int vMaxEntries=100;
  121.  
  122. /*******************************************************************************************/
  123.  
  124. void polygon_findminmax( XPoint *aPoints, int nPoints, int *xmin, int *xmax, int *ymin, int *ymax){
  125.   int i;
  126.   
  127.   *xmin=*xmax=aPoints[0].x;
  128.   *ymin=*ymax=aPoints[0].y;
  129.   for(i=1;i<nPoints;i++){
  130.     if(aPoints[i].x<*xmin) *xmin=aPoints[i].x;
  131.     if(aPoints[i].x>*xmax) *xmax=aPoints[i].x;
  132.     if(aPoints[i].y<*ymin) *ymin=aPoints[i].y;
  133.     if(aPoints[i].y>*ymax) *ymax=aPoints[i].y;
  134.   }
  135. }
  136.  
  137. void X11ClearPattern(Window win,int x,int y,int w,int h,int background){
  138.   SetAPen(drp,background /*X11DrawablesBackground[win]*/);
  139.   SetDrPt(drp,0xFFFF);
  140.   SetAfPt(drp,0,0);
  141.   SetDrMd(drp,JAM1);
  142.   BltPattern(drp,backfillrp.BitMap->Planes[0],X_relx+x,X_rely+y,X_relx+x+w,X_rely+y+h,backfillrp.BitMap->BytesPerRow);
  143.   WaitBlit();
  144.   prevgc=(GC)-1;
  145. }
  146.  
  147. void X11init_drawing(void){
  148.   aPoints=malloc(vMaxEntries*sizeof(XPoint));
  149.   if(!aPoints) X11resource_exit(DRAWING1);
  150. }
  151.  
  152. void X11Expand_Points(int n){
  153.   free(aPoints);
  154.   aPoints=malloc((n+50)*sizeof(XPoint));
  155.   vMaxEntries=n+50;
  156.   if(!aPoints) X11resource_exit(DRAWING2);
  157. }
  158.  
  159. void X11exit_drawing(void){
  160.   free(aPoints);
  161. }
  162.  
  163.  
  164. XDrawArc(d,win,gc,x,y,w,h,v1,v2)
  165.      Display *d;
  166.      Drawable win;
  167.      GC gc;
  168.      int x,y,v1,v2;
  169.      unsigned int w,h;
  170. {
  171.   float px0,py0,fx,fy,px1,py1;
  172.   int n;
  173.   int vX[200],vY[200];
  174.   int p=0;
  175.   boolean simple=True;
  176.   int type=Polygon_Open;
  177.   XPoint *points;
  178.   int np;
  179.   int error;
  180.  
  181. #ifdef DEBUGXEMUL_ENTRY
  182.   printf("(drawing)XDrawArc\n");
  183. #endif
  184.   if(win!=prevwin) if(!(drp=setup_win(win))) return;
  185.   if(gc!=prevgc) setup_gc(gc);
  186.   _Xfillfit(win,100);
  187.   if(h<2) h=2;
  188.   if(w<2) w=2;
  189.  
  190.   v1=v1>>6;
  191.   v2=v2>>6;
  192.   if(v1==0&&v2==360) type=Polygon_Closed;
  193.   if(v1!=0||v2!=360) simple=False;
  194.   if(x<0 || y<0 || x+w>X_width || y+h>X_height){
  195.     type=Polygon_Open;
  196.     simple=False;
  197.   }
  198.   if(simple){
  199.     if( gc->values.line_width<2 )
  200.       DrawEllipse(drp,X_relx+((w>>1)+x),X_rely+((h>>1)+y),(w>>1),(h>>1));
  201.     else {
  202.       error=AreaEllipse(drp,X_relx+(w>>1)+x,X_rely+(h>>1)+y,
  203.             (w>>1)+(gc->values.line_width>>1),(h>>1)+(gc->values.line_width>>1));
  204.       if( error==-1 ) return 0;
  205.       if( ((int)(w>>1)-(gc->values.line_width>>1)) >0 &&
  206.      ((int)(h>>1)-(gc->values.line_width>>1)) >0 )
  207.     error=AreaEllipse(drp,X_relx+(w>>1)+x,X_rely+(h>>1)+y,
  208.               (w>>1)-(gc->values.line_width>>1),(h>>1)-(gc->values.line_width>>1));
  209.       if( error==-1 ) return 0;
  210.       AreaEnd(drp);
  211.     }
  212.     return;
  213.   }
  214.  
  215.   px0=cos(rad(-(v1+v2)))*(w>>1);
  216.   py0=sin(rad(-(v1+v2)))*(h>>1);
  217.   fx=cos(rad(-5));
  218.   fy=sin(rad(-5));
  219.   if(vMaxEntries<200) X11Expand_Points(200);
  220.   if( gc->values.line_width<2 ){
  221.     aPoints[p].x=(int)(x+(w>>1)+px0); aPoints[p++].y=(int)((h>>1)+y+py0);
  222.     for(n=0;n<(int)(v2/5);n++){
  223.       px1=fx*px0+fy*py0;
  224.       py1=fx*py0-fy*px0;
  225.       aPoints[p].x=(int)((w>>1)+x+px1); aPoints[p++].y=(int)((h>>1)+y+py1*h/w);
  226.       px0=px1;
  227.       py0=py1;
  228.     }
  229. #ifdef DOCLIPPING
  230.     polygon_draw(drp,aPoints,p,X_relx,X_rely);
  231. #else
  232.     points=polygon_clip(p,aPoints,0,type,&np,1,1);
  233.     if(np) polygon_draw(drp,points,np,X_relx,X_rely);
  234.     if(points) free(points);
  235. #endif
  236.   } else /* wide lines */ { 
  237.     int p=0;
  238.     float f;
  239.  
  240.     if(((int)w-(int)gc->values.line_width)>0){
  241.       _Xfillfit(win,200);
  242.     }
  243. /*
  244.     px0=cos(rad(-(v1+v2)))*((int)(w>>1)+(gc->values.line_width>>1));
  245.     py0=sin(rad(-(v1+v2)))*((int)(w>>1)+(gc->values.line_width>>1));
  246.     x0=(int)(x+(w>>1)+px0);
  247.     y0=(int)(y+(w>>1)+py0);
  248. */
  249.     px0=(w>>1)+(gc->values.line_width>>1);
  250.     py0=0;
  251.     aPoints[p].x=(int)(x+w+(gc->values.line_width>>1)); aPoints[p++].y=y+(h>>1);
  252.     f=(float)((int)h+(gc->values.line_width>>1))/((int)w+(gc->values.line_width>>1));
  253.     for(n=0;n<(int)(v2/5);n++){
  254.       px1=fx*px0+fy*py0;
  255.       py1=fx*py0-fy*px0;
  256.       aPoints[p].x=(int)((w>>1)+x+px1); 
  257.       aPoints[p++].y=(int)((h>>1)+y+py1*f);
  258.       px0=px1;
  259.       py0=py1;
  260.     }
  261.  
  262.     
  263.     if(((int)w-(int)gc->values.line_width)>0){
  264.       int pn=1,n;
  265.       float f;
  266. #ifdef DOCLIPPING
  267. #ifdef TEST
  268.       polygon_draw(drp,aPoints,p,X_relx,X_rely);
  269. #else
  270.       AreaMove(drp,X_relx+aPoints[0].x,X_rely+aPoints[0].y);
  271.       for( n=1;n<p;n++ ){
  272.     AreaDraw(drp,X_relx+aPoints[n].x,X_rely+aPoints[n].y);
  273.       }
  274. #endif
  275. #else
  276.       points=polygon_clip(p,aPoints,1,Polygon_Closed,&np,1,0);
  277.       if(!np) {
  278.     if(points) free(points);
  279.     return;
  280.       }
  281.       if(AreaMove(drp,X_relx+points[0].x,X_rely+points[0].y)==-1){
  282.     printf("error!\n");
  283.     return 0;
  284.       }
  285.       for( n=1;n<np;n++ ){
  286.     if(AreaDraw(drp,X_relx+points[n].x,X_rely+points[n].y)==-1){
  287.       printf("error!\n");
  288.       return 0;
  289.     }
  290.       }
  291.       if(points) free(points);
  292. #endif
  293. /*
  294.       px0=cos(rad(-(v1+v2)))*((int)(w>>1)-(gc->values.line_width>>1));
  295.       py0=sin(rad(-(v1+v2)))*((int)(w>>1)-(gc->values.line_width>>1));
  296. */
  297.       px0=(w>>1)-(gc->values.line_width>>1);
  298.       py0=0;
  299.  
  300.       fx=cos(rad(-5)); fy=sin(rad(-5));
  301.       vX[0]=(int)(x+w-(gc->values.line_width>>1));
  302.       vY[0]=(int)(y+(h>>1));
  303.       f=(float)((int)h-(gc->values.line_width>>1))/((int)w-(gc->values.line_width>>1));
  304.       for(n=0;n<(int)(v2/5);n++){
  305.     px1=fx*px0+fy*py0;
  306.     py1=fx*py0-fy*px0;
  307.     vX[pn]=(int)((w>>1)+x+px1);
  308.         vY[pn++]=(int)((h>>1)+y+py1*f);
  309.     px0=px1; py0=py1;
  310.       }
  311.       if(v1==0 && v2==360)
  312.     AreaMove(drp,X_relx+vX[pn-1],X_rely+vY[pn-1]);
  313.       else
  314.     AreaDraw(drp,X_relx+vX[pn-1],X_rely+vY[pn-1]);
  315.       p=0;
  316.       for(n=pn-1;n>=0;n--){
  317.     aPoints[p].x=vX[n]; aPoints[p++].y=vY[n];
  318.       }
  319.     } else {
  320.       aPoints[p].x=x+(w>>1); aPoints[p++].y=y+(w>>1);
  321.       AreaMove(drp,X_relx+aPoints[0].x,X_rely+aPoints[0].y);
  322.     }
  323. #ifdef DOCLIPPING
  324. #ifdef TEST
  325.     polygon_draw(drp,aPoints,p,X_relx,X_rely);
  326. #else
  327.     for( n=1;n<p;n++ ){
  328.       AreaDraw(drp,X_relx+aPoints[n].x,X_rely+aPoints[n].y);
  329.     }
  330.     AreaEnd(drp);
  331. #endif
  332. #else
  333.     points=polygon_clip(p,aPoints,1,Polygon_Closed,&np,0,1);
  334.     if(!np){
  335.       if(points) free(points);
  336.       AreaEnd(drp);
  337.       return;
  338.     }
  339.     for( n=1;n<np;n++ ){
  340.       if(AreaDraw(drp,X_relx+points[n].x,X_rely+points[n].y)==-1){ 
  341.     printf("error!\n");
  342.     return 0;
  343.       }
  344.     }
  345.     AreaEnd(drp);
  346.     if(points) free(points);
  347. #endif
  348.   }
  349. }
  350.      
  351.  
  352. XDrawArcs(display, drawable, gc, arcs, narcs)
  353.      Display *display;
  354.      Drawable drawable;
  355.      GC gc;
  356.      XArc *arcs;
  357.      int narcs;
  358. {
  359.   int i;
  360.   for(i=0;i<narcs;i++)
  361.     XDrawArc(display,drawable,gc,arcs[i].x,arcs[i].y,arcs[i].width,arcs[i].height,arcs[i].angle1,arcs[i].angle2);
  362. }
  363.  
  364. XFillArc(d,win,gc,x,y,w,h,v1,v2)
  365.      Display *d;
  366.      Drawable win;
  367.      GC gc;
  368.      int x,y,v1,v2;
  369.      unsigned int w,h;
  370. {
  371.   float px0,py0,fx,fy,px1,py1;
  372.   int n;
  373.   int p=0;
  374.   boolean simple=True;
  375. /*  printf("(drawing)XFillArc %d %d %d %d %d %d\n",x,y,w,h,v1,v2);*/
  376. #ifdef DEBUGXEMUL_ENTRY
  377.   printf("(drawing)XFillArc\n");
  378. #endif
  379.  
  380.   if(win!=prevwin) if(!(drp=setup_win(win))) return;
  381.   if(gc!=prevgc) setup_gc(gc);
  382.  
  383.   if(h<2) h=2;
  384.   if(w<2) w=2;
  385.  
  386.   if(X11check_size(win,w,h)) return;
  387.   v1=v1>>6;
  388.   v2=v2>>6;
  389.   if(v1!=0||v2!=360) simple=False;
  390.   if(x<0 || y<0 || x+w>X_width || y+h>X_height) simple=False;
  391.  
  392.   if(simple){
  393.     if( X11InternalFill ){
  394.       X11Fit_InternalFill(w,h);
  395.       SetAfPt(&backfillrp,0,0);
  396.       SetDrMd(&backfillrp,JAM1);
  397.       SetAPen(&backfillrp,1);
  398.       AreaEllipse(&backfillrp,(w>>1),(h>>1),(w>>1),(h>>1));
  399.       AreaEnd(&backfillrp);
  400.       X11ClearPattern(win,x,y,w,h,gc->values.background);
  401. /*
  402.       BltMaskBitMapRastPort(X11FillBitMap,0,0,&backfillrp2,X_relx+x,X_rely+y,w,h,
  403.                 (ABC|ABNC|ANBC),backfillrp.BitMap->Planes[0]);
  404.       WaitBlit();
  405. */
  406.  
  407.       SetDrMd(drp,JAM2);
  408.       SetAPen(drp,gc->values.foreground);
  409.       SetBPen(drp,X11DrawablesBackground[win]);
  410.       prevgc=(GC)-1;
  411.       BltMaskBitMapRastPort(X11FillBitMap,0,0,&backfillrp2,0,0,w,h,
  412.               (ABC|ABNC|ANBC),backfillrp.BitMap->Planes[0]);
  413.       WaitBlit();
  414.       BltPattern(drp,backfillrp2.BitMap->Planes[0],X_relx+x,X_rely+y,X_relx+x+w,X_rely+y+h,backfillrp.BitMap->BytesPerRow);
  415.       WaitBlit();
  416.       return;
  417.     }
  418.     AreaEllipse(drp,X_relx+x+(w>>1),X_rely+y+(h>>1),(w>>1),(h>>1));
  419.     AreaEnd(drp);
  420.     return;
  421.   }
  422.  
  423.   px0=cos(rad(-(v1+v2)))*(w>>1);
  424.   py0=sin(rad(-(v1+v2)))*(h>>1);
  425.   fx=cos(rad(-5));
  426.   fy=sin(rad(-5));
  427.   if(gc->values.arc_mode==ArcPieSlice){
  428.     aPoints[p].x=(int)(x+(w>>1)); aPoints[p++].y=(int)(y+(h>>1));
  429.   }
  430.   aPoints[p].x=(int)(x+(w>>1)+px0); aPoints[p++].y=(int)(y+(h>>1)+py0);
  431.   for(n=0;n<(int)(v2/5);n++){
  432.     px1=fx*px0+fy*py0;
  433.     py1=fx*py0-fy*px0;
  434.     aPoints[p].x=(int)(x+(w>>1)+px1); aPoints[p++].y=(int)(y+(h>>1)+py1*h/w);
  435.     px0=px1;
  436.     py0=py1;
  437.   }
  438.   aPoints[p].x=(int)(x+(w>>1)); aPoints[p++].y=(int)(y+(h>>1));
  439.   {
  440.     int np;
  441.     XPoint *points;
  442.     points=polygon_clip(p,aPoints,1,Polygon_Closed,&np,1,1);
  443.     if(!np){
  444.       if(points) free(points);
  445.       return;
  446.     }
  447.     if( X11InternalFill ){
  448.       int xmin,xmax,ymin,ymax;
  449.  
  450.       polygon_findminmax(points,np,&xmin,&xmax,&ymin,&ymax);
  451.       X11Fit_InternalFill(xmax-xmin,ymax-ymin);
  452.       SetAfPt(&backfillrp,0,0);
  453.       SetDrMd(&backfillrp,JAM1);
  454.       SetAPen(&backfillrp,1);
  455.       X11FillPolygon(&backfillrp,points,np,xmin,ymin,1);
  456.       X11ClearPattern(win,xmin,ymin,xmax-xmin,ymax-ymin,gc->values.background);
  457. /*
  458.       BltMaskBitMapRastPort(X11FillBitMap,0,0,drp,X_relx+xmin,X_rely+ymin,xmax-xmin,ymax-ymin,
  459.                 (ABC|ABNC|ANBC),backfillrp.BitMap->Planes[0]);
  460.       WaitBlit();
  461. */
  462.       SetDrMd(drp,JAM2);
  463.       SetAPen(drp,gc->values.foreground);
  464.       SetBPen(drp,X11DrawablesBackground[win]);
  465.       prevgc=(GC)-1;
  466.       BltMaskBitMapRastPort(X11FillBitMap,0,0,&backfillrp2,0,0,xmax-xmin,ymax-ymin,
  467.                 (ABC|ABNC|ANBC),backfillrp.BitMap->Planes[0]);
  468.       WaitBlit();
  469.       BltPattern(drp,backfillrp2.BitMap->Planes[0],X_relx+xmin,X_rely+ymin,X_relx+xmax,X_rely+ymax,backfillrp.BitMap->BytesPerRow);
  470.       WaitBlit();
  471.     } else
  472.       if(np) X11FillPolygon(drp,points,np,-X_relx,-X_rely,0);
  473.     prevgc=(GC)-1;
  474.     if(points) free(points);
  475.   }
  476. }
  477.  
  478. XFillArcs(display, drawable, gc, arcs, narcs)
  479.      Display *display;
  480.      Drawable drawable;
  481.      GC gc;
  482.      XArc *arcs;
  483.      int narcs;
  484. {
  485.   int i;
  486.   for(i=0;i<narcs;i++)
  487.     XFillArc(display,drawable,gc,arcs[i].x,arcs[i].y,arcs[i].width,arcs[i].height,arcs[i].angle1,arcs[i].angle2);
  488. }
  489.  
  490. XDrawPoint(d,win,gc,x1,y1)
  491.      Display *d;
  492.      Drawable win;
  493.      GC gc;
  494.      int x1,y1;
  495. {
  496. #ifdef DEBUGXEMUL_ENTRY
  497.   printf("(drawing)XDrawPoint\n");
  498. #endif
  499.   if(win!=prevwin) if(!(drp=setup_win(win))) return;
  500.   if(gc!=prevgc) setup_gc(gc);
  501.  
  502.   WritePixel(drp,X_relx+x1,X_rely+y1);
  503. }
  504.  
  505. MakeBevel(XPoint *xp1,XPoint *xp2){
  506.   xp1[0].x=xp1[3].x;
  507.   xp1[0].y=xp1[3].y;
  508.   xp1[1].x=xp1[2].x;
  509.   xp1[1].y=xp1[2].y;
  510.   xp1[2].x=xp2[1].x;
  511.   xp1[2].y=xp2[1].y;
  512.   xp1[3].x=xp2[0].x;
  513.   xp1[3].y=xp2[0].y;
  514. }
  515.  
  516. #define distance(x1,y1,x2,y2) (sqrt((double)(y2-y1)*(y2-y1)+(x2-x1)*(x2-x1)))
  517.  
  518. void GetCrossing(XPoint p1,XPoint p2,XPoint p3,XPoint p4,XPoint *pRet);
  519.  
  520. void GetCrossing(p1,p2,p3,p4,pRet)
  521. XPoint p1,p2,p3,p4,*pRet;
  522. {
  523.   float d1,d2;
  524.   float ycross1,ycross2;
  525.  
  526.   assert(pRet);
  527.  
  528.   if((p2.x-p1.x)!=0){
  529.     d1=(float)(p2.y-p1.y)/(p2.x-p1.x);
  530.     ycross1=p1.y-p1.x*d1;
  531.     if((p4.x-p3.x)!=0){
  532.       d2=(float)(p4.y-p3.y)/(p4.x-p3.x);
  533.       ycross2=p3.y-p3.x*d2;
  534.       pRet->x=(int)((ycross2-ycross1)/(d1-d2));
  535.       pRet->y=(int)(d1*pRet->x+ycross1);
  536.     } else {
  537.       pRet->x=p4.x;
  538.       pRet->y=d1*p4.x+ycross1;
  539.     }
  540.   } else {
  541.     if((p4.x-p3.x)!=0){
  542.       d2=(float)(p4.y-p3.y)/(p4.x-p3.x);
  543.       ycross2=p3.y-p3.x*d2;
  544.       pRet->x=p2.x;
  545.       pRet->y=d2*p2.x+ycross2;
  546.     } else {
  547.       pRet->x=p1.x;
  548.       pRet->y=p1.y;
  549.     }
  550.   }
  551.  
  552. }
  553.  
  554. MakeMiter(Display *d,Drawable win,GC gc,XPoint *xp1,XPoint *xp2){
  555. /*
  556.   float d1,d2;
  557.   float ycross1,ycross2;
  558.   int xcross,ycross;
  559. */
  560.   int p1=0,p2=3;
  561.   XPoint p;
  562.  
  563.   if(distance(xp1[1].x,xp1[1].y,xp2[2].x,xp2[2].y)>
  564.      distance(xp1[0].x,xp1[0].y,xp2[3].x,xp2[3].y)) {
  565.        p1=2; p2=1;
  566.      }
  567. /*
  568.   if((xp1[0].x-xp1[3].x)!=0){
  569.     d1=(float)(xp1[p2].y-xp1[p1].y)/(xp1[p2].x-xp1[p1].x);
  570.     ycross1=xp1[p1].y-xp1[p1].x*d1;
  571.     if((xp2[0].x-xp2[3].x)!=0){
  572.       d2=(float)(xp2[p2].y-xp2[p1].y)/(xp2[p2].x-xp2[p1].x);
  573.       ycross2=xp2[p1].y-xp2[p1].x*d2;
  574.       xcross=(int)((ycross2-ycross1)/(d1-d2));
  575.       ycross=(int)(d1*xcross+ycross1);
  576.     } else {
  577.       xcross=xp2[p2].x;
  578.       ycross=d1*xp2[p2].x+ycross1;
  579.     }
  580.   } else {
  581.     if((xp2[0].x-xp2[3].x)!=0){
  582.       d2=(float)(xp2[p2].y-xp2[p1].y)/(xp2[p2].x-xp2[p1].x);
  583.       ycross2=xp2[p1].y-xp2[p1].x*d2;
  584.       xcross=xp1[p2].x;
  585.       ycross=d2*xp1[p2].x+ycross2;
  586.     } else {
  587.       xcross=xp1[1].x;
  588.       ycross=xp1[1].y;
  589.     }
  590.   }
  591. */
  592.   GetCrossing(xp1[p1],xp1[p2],xp2[p1],xp2[p2],&p);
  593.  
  594.   if( p2==3 ){
  595.     xp1[0].x=xp1[3].x; xp1[0].y=xp1[3].y;
  596.     xp1[1].x=xp1[2].x; xp1[1].y=xp1[2].y;
  597.     xp1[2].x=xp2[0].x; xp1[2].y=xp2[0].y;
  598.     xp1[3].x=p.x;   xp1[3].y=p.y;
  599.   } else {
  600.     xp1[0].x=xp1[2].x; xp1[0].y=xp1[2].y;
  601.     xp1[1].x=p.x;   xp1[1].y=p.y;
  602.     xp1[2].x=xp2[1].x; xp1[2].y=xp2[1].y;
  603.     xp1[3].x=xp1[3].x; xp1[3].y=xp1[3].y;
  604.   }
  605. }
  606.  
  607. XDrawLine(Display  *d,Drawable win,GC gc,int x1,int y1,int x2,int y2){
  608.   float fx,fy,px1,py1;
  609.   int p=0;
  610. #ifdef DEBUGXEMUL_ENTRY
  611.   printf("(drawing)XDrawLine %d %d %d %d %d\n",win,x1,y1,x2,y2);
  612. #endif
  613.   if(win!=prevwin) if(!(drp=setup_win(win))) return;
  614.   if(gc!=prevgc) setup_gc(gc);
  615.  
  616.   if( gc->values.line_width<2 ){
  617.     int np;
  618.     XPoint *points;
  619.     aPoints[p].x=x1; aPoints[p++].y=y1;
  620.     aPoints[p].x=x2; aPoints[p++].y=y2;
  621.     points=polygon_clip(p,aPoints,0,Polygon_Open,&np,1,1);
  622.     if(np) polygon_draw(drp,points,np,X_relx,X_rely);
  623.     prevgc=(GC)-1;
  624.     if(points) free(points);
  625.   } else {
  626.     float vRad;
  627.     int vHalfWidth=(int)(gc->values.line_width/2);
  628.     vRad=distance(x1,y1,x2,y2);;
  629.     fx=(y2-y1)/vRad;
  630.     fy=(x2-x1)/vRad;
  631.     px1=fx*vHalfWidth;
  632.     py1=-fy*vHalfWidth;
  633.     xp[0].x=x1+px1;
  634.     xp[0].y=y1+py1;
  635.     xp[1].x=x1-px1;
  636.     xp[1].y=y1-py1;
  637.     xp[2].x=x2-px1;
  638.     xp[2].y=y2-py1;
  639.     xp[3].x=x2+px1;
  640.     xp[3].y=y2+py1;
  641.     XFillPolygon(d,win,gc,xp,4,0,0);
  642.   }
  643. }
  644.  
  645. XDrawLines(Display *d,Drawable win,GC gc,XPoint array[],int entries,int mode)
  646. {
  647.   int i;
  648.   int p=0;
  649.   int np;
  650.   XPoint *points;
  651. #ifdef DEBUGXEMUL_ENTRY
  652.   printf("(drawing)XDrawLines\n");
  653. #endif
  654.   if(win!=prevwin) if(!(drp=setup_win(win))) return;
  655.   if(gc!=prevgc) setup_gc(gc);
  656.   if(entries>vMaxEntries){
  657.     X11Expand_Points(entries);
  658.   }
  659.   if(mode==CoordModeOrigin){
  660.     aPoints[p].x=array[0].x; aPoints[p++].y=array[0].y;
  661. /*
  662.     if(X_relx!=0||X_rely!=0){
  663. */
  664.       if( gc->values.line_width<2 ){
  665.     for(i=1;i<entries;i++){
  666.       aPoints[p].x=array[i].x; aPoints[p++].y=array[i].y;
  667.     }
  668.     points=polygon_clip(p,aPoints,0,Polygon_Open,&np,1,1);
  669.     if(np) polygon_draw(drp,points,np,X_relx,X_rely);
  670.     if(points) free(points);
  671.       } else {
  672.     XPoint xp2[4];
  673.     XDrawLine(d,win,gc,array[0].x,array[0].y,array[1].x,array[1].y);
  674.     for(i=2;i<entries;i++){
  675.       memcpy(xp2,xp,sizeof(XPoint)*4);
  676.       XDrawLine(d,win,gc,array[i-1].x,array[i-1].y,array[i].x,array[i].y);
  677.       if(gc->values.join_style==JoinBevel){
  678.         MakeBevel(xp2,xp);
  679.       }  else if(gc->values.join_style==JoinMiter){
  680.         MakeMiter(d,win,gc,xp2,xp);
  681.       } else if(gc->values.join_style==JoinRound){
  682.         XFillArc(d,win,gc,array[i-1].x-(gc->values.line_width>>1),array[i-1].y-(gc->values.line_width>>1),gc->values.line_width,gc->values.line_width,0,360<<6);
  683.       } else
  684.         MakeBevel(xp2,xp);
  685.       if(gc->values.join_style!=JoinRound)
  686.         XFillPolygon(d,win,gc,xp2,4,0,0);
  687.     }
  688.       }
  689. /*
  690.     } else {
  691.       PolyDraw(drp,entries,(WORD*)array);
  692.     }
  693. */
  694.   }else{
  695.     int px=array[0].x,py=array[0].y;
  696.     if( gc->values.line_width<2 ){
  697.       for(i=0;i<entries-1;i++){
  698.     aPoints[p].x=px; aPoints[p++].y=py;
  699.     aPoints[p].x=px+array[i+1].x; aPoints[p++].y=py+array[i+1].y;
  700.     px=px+array[i+1].x;
  701.     py=py+array[i+1].y;
  702.       }
  703.       points=polygon_clip(p,aPoints,0,Polygon_Open,&np,1,1);
  704.       if(np) polygon_draw(drp,points,np,X_relx,X_rely);
  705.       if(points) free(points);
  706.     } else {
  707.       for(i=0;i<entries-1;i++){
  708.     XDrawLine(d,win,gc,px,py,px+array[i+1].x,py+array[i+1].y);
  709.     px=px+array[i+1].x;
  710.     py=py+array[i+1].y;
  711.       }
  712.     }
  713.   }
  714.   return;
  715. }
  716.  
  717. XFillRectangle(d,win,gc,x1,y1,w,h)
  718.      Display *d;
  719.      Drawable win;
  720.      GC gc;
  721.      int x1,y1;
  722.      unsigned int w,h;
  723. {
  724.   int width=w,height=h;
  725. #ifdef DEBUGXEMUL_ENTRY
  726.   printf("(drawing)XFillRectangle\n");
  727. #endif
  728.   if(win!=prevwin) if(!(drp=setup_win(win))) return;
  729.   if(gc!=prevgc) setup_gc(gc);
  730. /*
  731.   printf("win %d X_relx %d X_rely %d [%d %d] [%d %d]\n",win,X_relx,X_rely,x1,y1,w,h);
  732. */
  733.  
  734.   if(x1+width<0||y1+height<0||x1>X_width||y1>X_height) return;
  735.   if((int)x1<0){
  736.     width+=x1;
  737.     x1=0;
  738.   }
  739.   if((int)y1<0){
  740.     height+=y1;
  741.     y1=0;
  742.   }
  743.   if((int)(+x1+width)>=(int)X_width){
  744.     width=X_width-x1;
  745.     if(width<=0) return(0);
  746.   }
  747.   if((int)(y1+height)>=(int)X_height){
  748.     height=X_height-y1;
  749.     if(height<=0) return(0);
  750.   }
  751.   if(width<0){
  752.     x1=x1+width;
  753.     width=-width;
  754.   }
  755.   if(height<0){
  756.     y1=y1+height;
  757.     height=-height;
  758.   }
  759.   if(width<1||height<1) return;
  760.  
  761.   if( X11InternalFill ){
  762.     int blitop=(ABC|ABNC|ANBC);
  763.     int olddrmd;
  764.     int oldfg,oldbg;
  765.  
  766.     X11Fit_InternalFill(width,height);
  767.     XClearArea(d,win,x1,y1,width,height,0);
  768.     if(!CG.bNeedClip){
  769.       SetDrMd(drp,JAM1);
  770.       SetAPen(drp,0);
  771.       RectFill(&backfillrp,0,0,width-1,height-1);
  772.     }
  773.     else {
  774.       BltBitMapRastPort(CG.pClipBM,0,0,&backfillrp,0,0,width,height,0xC0);
  775.       WaitBlit();
  776.     }
  777.     olddrmd=drp->DrawMode;
  778.     oldfg=drp->FgPen;
  779.     oldbg=drp->BgPen;
  780.     SetDrMd(drp,JAM2);
  781.     SetAPen(drp,gc->values.foreground);
  782.     SetBPen(drp,X11DrawablesBackground[win]);
  783.     BltMaskBitMapRastPort(X11FillBitMap,0,0,&backfillrp2,0,0,width,height,blitop,
  784.               backfillrp.BitMap->Planes[0]);
  785.     WaitBlit();
  786.     BltPattern(drp,backfillrp2.BitMap->Planes[0],X_relx+x1,X_rely+y1,X_relx+x1+width,X_rely+y1+height,backfillrp.BitMap->BytesPerRow);
  787.     WaitBlit();
  788.  
  789.     drp->DrawMode=olddrmd;
  790.     drp->FgPen=oldfg;
  791.     drp->BgPen=oldbg;
  792.     return;
  793.   }
  794.   if(!CG.bNeedClip)
  795.     RectFill(drp,X_relx+x1,X_rely+y1,X_relx+x1+width-1,X_rely+y1+height-1);
  796.   else{
  797.     BltBitMapRastPort(CG.pClipBM,0,0,drp,X_relx+x1,X_rely+y1,width,height,0xC0);
  798.     WaitBlit();
  799.   }
  800.   return;
  801. }
  802.  
  803. XFillRectangles(display, drawable, gc, rectangles, nrectangles)
  804.      Display *display;
  805.      Drawable drawable;
  806.      GC gc;
  807.      XRectangle *rectangles;
  808.      int nrectangles;
  809. {
  810.   int i;
  811.   for(i=0;i<nrectangles;i++)
  812.     XFillRectangle(display,drawable,gc,rectangles[i].x,rectangles[i].y,rectangles[i].width,rectangles[i].height);
  813. }
  814.  
  815. polygon_draw(struct RastPort *drp,XPoint *aPoints,int nPoints,int xmin,int ymin){
  816.   int n;
  817.   Move(drp,xmin+aPoints[0].x,ymin+aPoints[0].y);
  818.   for( n=1;n<nPoints;n++ ){
  819.     Draw(drp,xmin+aPoints[n].x,ymin+aPoints[n].y);
  820.   }
  821. }
  822.  
  823. XDrawRectangle(d,win,gc,x1,y1,w,h)
  824. Display *d;
  825. GC gc;
  826. Drawable win;
  827. int x1,y1;
  828. unsigned int w,h;
  829. {
  830.   int p=0;
  831. #ifdef DEBUGXEMUL_ENTRY
  832.   printf("(drawing)XDrawRectangle\n");
  833. #endif
  834.   if(win!=prevwin) if(!(drp=setup_win(win))) return;
  835.   if(gc!=prevgc) setup_gc(gc);
  836.  
  837.   if( gc->values.line_width<2 ){
  838.     int np;
  839.     XPoint *points;
  840.     aPoints[p].x=x1; aPoints[p++].y=y1;
  841.     aPoints[p].x=x1; aPoints[p++].y=y1+h;
  842.     aPoints[p].x=x1+w; aPoints[p++].y=y1+h;
  843.     aPoints[p].x=x1+w; aPoints[p++].y=y1;
  844.     aPoints[p].x=x1; aPoints[p++].y=y1;
  845.     points=polygon_clip(p,aPoints,0,Polygon_Open,&np,1,1);
  846.     if(np) polygon_draw(drp,points,np,X_relx,X_rely);
  847.     if(points) free(points);
  848.   } else {
  849.     XDrawLine(d,win,gc,x1,y1,x1,y1+h);
  850.     XDrawLine(d,win,gc,x1,y1+h,x1+w,y1+h); 
  851.     XDrawLine(d,win,gc,x1+w,y1+h,x1+w,y1);
  852.     XDrawLine(d,win,gc,x1+w,y1,x1,y1);
  853.  }
  854.   return;
  855. }
  856.  
  857. XDrawRectangles(display, drawable, gc, rectangles, nrectangles)
  858.      Display *display;
  859.      Drawable drawable;
  860.      GC gc;
  861.      XRectangle rectangles[];
  862.      int nrectangles;
  863. {
  864.   int i;
  865.   for(i=0;i<nrectangles;i++)
  866.     XDrawRectangle(display,drawable,gc,rectangles[i].x,rectangles[i].y,rectangles[i].width,rectangles[i].height);
  867. }
  868.  
  869. int X11polysizex,X11polysizey;
  870.  
  871. X11FillPolygon(struct RastPort *drp,XPoint *points,int nPoints,int xmin,int ymin, char black){
  872.   int i;
  873.   if(black){
  874.     SetAfPt(drp,0,0);
  875.     SetDrMd(drp,JAM1);
  876.     SetAPen(drp,1);
  877.   }
  878.   AreaMove(drp,points[0].x-xmin,points[0].y-ymin);
  879.   for(i=1;i<nPoints;i++) 
  880.     AreaDraw(drp,points[i].x-xmin,points[i].y-ymin);
  881.   AreaEnd(drp);
  882.   prevgc=(GC)-1;
  883. }
  884.  
  885. XFillPolygon(Display *d,Drawable win,GC gc,XPoint *xp,int num,int shape,int mode){
  886.   int clipped=0;
  887.   int xmin,xmax,ymin,ymax;
  888.   XPoint *points=xp;
  889.   int np=num;
  890. #ifdef DEBUGXEMUL_ENTRY
  891.   printf("(drawing)XFillPolygon %d\n",num);
  892. #endif
  893.   if(num<1){
  894.     printf("no entries in fill\n");
  895.     return 0;
  896.   }
  897.   if(win!=prevwin) if(!(drp=setup_win(win))) return;
  898.   if(gc!=prevgc) setup_gc(gc);
  899.  
  900.   if(X11check_size(win,X11polysizex,X11polysizey)) return;
  901.   polygon_findminmax(xp,num,&xmin,&xmax,&ymin,&ymax);
  902.   if( xmin<0 || xmax>X_width || ymin<0 || ymax>X_height ){
  903.     points=polygon_clip(num,xp,True,Polygon_Closed,&np,1,1);
  904.     if(!np){
  905.       if(points) free(points);
  906.       return;
  907.     }
  908.     clipped=1;
  909.   }
  910.   _Xfillfit(win,np);
  911.   if( X11InternalFill ){
  912.     X11Fit_InternalFill(xmax-xmin,ymax-ymin);
  913.     X11FillPolygon(&backfillrp,points,np,xmin,ymin,1);
  914.     X11ClearPattern(win,xmin,ymin,xmax-xmin,ymax-ymin,gc->values.background);
  915. /*
  916.     BltMaskBitMapRastPort(X11FillBitMap,0,0,drp,X_relx+xmin,X_rely+ymin,xmax-xmin,ymax-ymin,
  917.               (ABC|ABNC|ANBC),backfillrp.BitMap->Planes[0]);
  918.     WaitBlit();
  919. */
  920.     SetDrMd(drp,JAM2);
  921.     SetAPen(drp,gc->values.foreground);
  922.     SetBPen(drp,X11DrawablesBackground[win]);
  923.     prevgc=(GC)-1;
  924.     BltMaskBitMapRastPort(X11FillBitMap,0,0,&backfillrp2,0,0,xmax-xmin,ymax-ymin,
  925.               (ABC|ABNC|ANBC),backfillrp.BitMap->Planes[0]);
  926.     WaitBlit();
  927.     BltPattern(drp,backfillrp2.BitMap->Planes[0],X_relx+xmin,X_rely+ymin,X_relx+xmax,X_rely+ymax,backfillrp.BitMap->BytesPerRow);
  928.     WaitBlit();
  929.   } else {
  930.     X11FillPolygon(drp,points,np,-X_relx,-X_rely,0);
  931.     prevgc=(GC)-1;
  932.   }
  933.   if(clipped && points) free(points);
  934. }
  935.  
  936. XSetFunction(display, gc, function)
  937.      Display *display;
  938.      GC gc;
  939.      int function;
  940. {
  941. /*  struct Window *win=RootWindowOfScreen(DefaultScreenOfDisplay(display));*/
  942. #ifdef DEBUGXEMUL
  943.   printf("(events)XSetFunction\n");
  944. #endif
  945.   gc->values.function=function;
  946. /*
  947.   if(function==GXinvert) SetDrMd(drp,COMPLEMENT);
  948.   else SetDrMd(drp,JAM1);
  949. */
  950.   prevgc=(GC)-1;
  951.   return(0);
  952. }
  953.  
  954. XDrawPoints(display, win, gc, points, npoints, mode)
  955.      Display *display;
  956.      Drawable win;
  957.      GC gc;
  958.      XPoint *points;
  959.      int npoints;
  960.      int mode;
  961. {/*             File 'xast.o'*/
  962.   int i;
  963. #ifdef DEBUGXEMUL_ENTRY
  964.   printf("XDrawPoints\n");
  965. #endif
  966.   if(win!=prevwin) if(!(drp=setup_win(win))) return;
  967.   if(gc!=prevgc) setup_gc(gc);
  968.  
  969.   for(i=0;i<npoints;i++)
  970.     WritePixel(drp,X_relx+points[i].x,X_rely+points[i].y);
  971. /*    XDrawPoint(display,win,gc,points[i].x,points[i].y);*/
  972.   return(0);
  973. }
  974.  
  975. char *XGetAtomName(Display *d,Atom a){/*            File 'do_simple.o'*/
  976. #if (DEBUGXEMUL_ENTRY) || (DEBUGXEMUL_WARNING)
  977.   printf("WARNING: XGetAtomName\n");
  978. #endif
  979.   return(0);
  980. }
  981.  
  982. XmuGetHostname(char *name,int length){/*          File 'x11perf.o'*/
  983.   char *tmpstr=getenv("hostname");
  984. #ifdef DEBUGXEMUL_ENTRY
  985.   printf("XmuGetHostname\n");
  986. #endif
  987.   if(tmpstr){
  988.     strncpy(name,tmpstr,length);
  989.     free(tmpstr);
  990.   }
  991.   else strcpy(name,"Unknown");
  992.   return(0);
  993. }
  994.  
  995. X_GETTIMEOFDAY(struct timeval *tp){/*          File 'x11perf.o'*/
  996.   unsigned int clock[2];
  997.   int x=timer(clock);
  998. #ifdef DEBUGXEMUL_ENTRY
  999.   printf("X_GETTIMEOFDAY\n");
  1000. #endif
  1001.   if(!x){
  1002.     tp->tv_sec=clock[0];
  1003.     tp->tv_usec=clock[1];
  1004.   }else{
  1005.     tp->tv_sec=0;
  1006.     tp->tv_usec=0;
  1007.   }
  1008.   return(0);
  1009. }
  1010.  
  1011. int _Xdash_list[]={0xffff,0xeeee,0xf0f0,0xff00,0x5f5f}; /* have to fake it..*/
  1012. /* solid, dotted, dashed, long dashed, dot-dashed */
  1013.  
  1014. XSetLineAttributes(display, gc, line_width, line_style,
  1015.            cap_style, join_style)
  1016.      Display *display;
  1017.      GC gc;
  1018.      unsigned int line_width;
  1019.      int line_style;
  1020.      int cap_style;
  1021.      int join_style;
  1022. {/*      File 'xvlib.o'*/
  1023. #ifdef DEBUGXEMUL
  1024.   printf("XSetLineAttributes style %d width %d\n",line_style,line_width);
  1025. #endif
  1026.   gc->values.line_style=line_style;
  1027.   gc->values.line_width=line_width;
  1028.   gc->values.cap_style=cap_style;
  1029.   gc->values.join_style=join_style;
  1030.   switch(line_style){
  1031.   case LineSolid: Xdash=0xffff;break;
  1032.   case LineOnOffDash: Xdash=0xaaaa;break;
  1033.   case LineDoubleDash: Xdash=0xff00;break;
  1034.   }
  1035.   prevgc=(GC)-1;
  1036.   return(0);
  1037. }
  1038.  
  1039. XDrawSegments(d, win, gc, segments, nsegments)
  1040.      Display *d;
  1041.      Drawable win;
  1042.      GC gc;
  1043.      XSegment *segments;
  1044.      int nsegments;
  1045. {
  1046.   int i;
  1047. #ifdef DEBUGXEMUL
  1048.   printf("XDrawSegments\n");
  1049. #endif
  1050.   if(win!=prevwin) if(!(drp=setup_win(win))) return;
  1051.   if(gc!=prevgc) setup_gc(gc);
  1052.   if(nsegments*2>vMaxEntries){
  1053.     X11Expand_Points(nsegments*2);
  1054.   }
  1055.  
  1056.   if( gc->values.line_width<2 ){
  1057.     XPoint *points;
  1058.     int np;
  1059.     for(i=0;i<nsegments;i++){
  1060.       points=polygon_clip(2,(XPoint*)&segments[i],0,Polygon_Open,&np,1,1);
  1061.       if(np) polygon_draw(drp,points,np,X_relx,X_rely);
  1062.       if(points) free(points);
  1063.     }
  1064.   } else {
  1065.     for(i=0;i<nsegments;i++){
  1066.       XDrawLine(d,win,gc,segments[i].x1,segments[i].y1,segments[i].x2,segments[i].y2);
  1067.     }
  1068.   }
  1069.  
  1070.   return(0);
  1071. }
  1072.  
  1073. /* polygon clipping */
  1074.  
  1075. enum {
  1076.   LEFTEDGE=0,
  1077.   RIGHTEDGE,
  1078.   TOPEDGE,
  1079.   BOTTOMEDGE,
  1080. };
  1081.  
  1082. int new_edge[4];
  1083. XPoint aFirstPoint[4],aS[4];
  1084.  
  1085. boolean inside( XPoint p, int edge ){
  1086.   switch ( edge ){
  1087.   case LEFTEDGE:
  1088.     if( p.x>=0 ) return True;
  1089.     break;
  1090.   case RIGHTEDGE:
  1091.     if( p.x<=X_width ) return True;
  1092.     break;
  1093.   case TOPEDGE:
  1094.     if( p.y>=0 ) return True;
  1095.     break;
  1096.   case BOTTOMEDGE:
  1097.     if( p.y<=X_height ) return True;
  1098.     break;
  1099.   }
  1100.   return False;
  1101. }
  1102.  
  1103. boolean cross( XPoint p, XPoint s, int edge ){
  1104.   switch ( edge ){
  1105.   case LEFTEDGE:
  1106. /*
  1107.     if( p.y<0 && s.y < 0 || p.y>X_height && s.y>X_height ) return False;
  1108. */
  1109.     if( p.x<0 && s.x>=0 || p.x>=0 && s.x<0 ) return True;
  1110.     break;
  1111.   case RIGHTEDGE:
  1112. /*
  1113.     if( p.y<0 && s.y < 0 || p.y>X_height && s.y>X_height ) return False;
  1114. */
  1115.     if( p.x<X_width && s.x>=X_width || p.x>=X_width && s.x<X_width ) return True;
  1116.     break;
  1117.   case TOPEDGE:
  1118. /*
  1119.     if( p.x<0 && s.x < 0 || p.x>X_width && s.x>X_width ) return False;
  1120. */
  1121.     if( p.y<0 && s.y>=0 || p.y>=0 && s.y<0 ) return True;
  1122.     break;
  1123.   case BOTTOMEDGE:
  1124. /*
  1125.     if( p.x<0 && s.x < 0 || p.x>X_width && s.x>X_width ) return False;
  1126. */
  1127.     if( p.y<X_height && s.y>=X_height || p.y>=X_height && s.y<X_height ) return True;
  1128.     break;
  1129.   }
  1130.   return False;
  1131. }
  1132.  
  1133. XPoint *aXP;
  1134. int nOutput;
  1135.  
  1136. output_vertex( XPoint p ){
  1137.   aXP[nOutput++]=p;
  1138. }
  1139.  
  1140. XPoint find_intersection( XPoint p, XPoint s, int edge ){
  1141.   XPoint r;
  1142.   XPoint p1,p2;
  1143. /*
  1144.   float ycross;
  1145.   float d1;
  1146.   d1=(float)(p.y-s.y)/(p.x-s.x);
  1147. */
  1148.  
  1149.   switch ( edge ){
  1150.   case LEFTEDGE:
  1151.     p1.x=0; p1.y=0;
  1152.     p2.x=0; p2.y=X_height;
  1153.     GetCrossing(p,s,p1,p2,&r);
  1154. /*
  1155.     r.x=0;
  1156.     r.y=p.y-p.x*d1;
  1157. */
  1158.     break;
  1159.   case RIGHTEDGE:
  1160.     p1.x=X_width; p1.y=0;
  1161.     p2.x=X_width; p2.y=X_height;
  1162.     GetCrossing(p,s,p1,p2,&r);
  1163. /*
  1164.     r.x=X_width;
  1165.     r.y=p.y-p.x*d1+X_width*d1;
  1166. */
  1167.     break;
  1168.   case TOPEDGE:
  1169.     p1.x=0; p1.y=0;
  1170.     p2.x=X_width; p2.y=0;
  1171.     GetCrossing(p,s,p1,p2,&r);
  1172.  
  1173. /*
  1174.     ycross=p.y-p.x*d1;
  1175.     r.x=-ycross/d1;
  1176.     r.y=0;
  1177. */
  1178.     break;
  1179.   case BOTTOMEDGE:
  1180.     p1.x=0; p1.y=X_height;
  1181.     p2.x=X_width; p2.y=X_height;
  1182.     GetCrossing(p,s,p1,p2,&r);
  1183.  
  1184. /*
  1185.     ycross=p.y-p.x*d1;
  1186.     r.x=(X_height-ycross)/d1;
  1187.     r.y=X_height;
  1188. */
  1189.     break;
  1190.   }
  1191.   return r;
  1192. }
  1193.  
  1194. void clip_this( XPoint p, int edge ){
  1195.   XPoint i;
  1196.  
  1197.   if( new_edge[edge]){
  1198.     aFirstPoint[edge]=p;
  1199.     new_edge[edge]=False;
  1200.   } else {
  1201.     if( cross(p,aS[edge],edge) ){
  1202.       i=find_intersection(p,aS[edge],edge);
  1203.       if( edge<3 ) clip_this(i,edge+1);
  1204.       else output_vertex(i);
  1205.     }
  1206.   }
  1207.   aS[edge]=p;
  1208.   if( inside(p,edge) )
  1209.     if( edge<3 ) clip_this(p,edge+1);
  1210.     else output_vertex(p);
  1211. }
  1212.  
  1213. void clip_closer(void){
  1214.   XPoint i;
  1215.   int edge;
  1216.  
  1217.   for( edge=0; edge<4; edge++ ){
  1218.     if( cross(aS[edge],aFirstPoint[edge],edge) ){
  1219.       i= find_intersection(aS[edge],aFirstPoint[edge],edge);
  1220.       if( edge<3 ) clip_this(i,edge+1);
  1221.       else output_vertex(i);
  1222.     }
  1223.   }
  1224. }
  1225.  
  1226. XPoint *polygon_clip( int nPoints,
  1227.               XPoint *points,
  1228.               boolean bFill,
  1229.               int PolygonType,
  1230.               int *nPointsReturn,
  1231.               int move,
  1232.               int end ){
  1233.   XPoint p;
  1234.   int n;
  1235.  
  1236.   nOutput=0;
  1237.   aXP=malloc(sizeof(XPoint)*nPoints*2);
  1238.   if(!aXP) X11resource_exit(DRAWING3);
  1239.   for( n=0; n<4; n++ )
  1240.     new_edge[n]=True;
  1241.   for( n=0; n<nPoints; n++ ){
  1242.     p.x=points[n].x;
  1243.     p.y=points[n].y;
  1244.     clip_this(p,0);
  1245.   }
  1246.   if( nOutput>2 && PolygonType==Polygon_Closed )
  1247.     clip_closer();
  1248.  
  1249.   *nPointsReturn=nOutput;
  1250.   if(!nOutput){
  1251.     free(aXP);
  1252.     return NULL;
  1253.   }
  1254.   return aXP;
  1255. }
  1256.